import { LogType, saveLog } from "../utils/LogUtil"
import { checkActor } from "../utils/mirUtil"
import { getArrayItem, randomInRange } from "../utils/utls"
import { ActorNkeyEnum, ActorSkeyEnum, MaxIntNum, MaxPercentNum } from "../配置/基础配置"
import { AllSlaveSet, DogSet, getSlaveAddAbiBySkill, KulouSet, SkillSlaveNumSet, SlaveSkillList } from "../配置/宝宝配置"
import { loopMongen } from "./FreshMon"

//每级增加血量 基础血量百分比
const HpAddLevel = 5
//每级增加的防御魔域
const AcAddLevel = 0.05
//每级增加的攻击
const DcAddLevel = 0.05


//血量继承比例
const HpAddPer = 0.5
//防御继承比例
const AcAddPer = 0.1
//攻击继承比例
const DcAddPer = 0.2
//基础宝宝数量(不算装备加成)
const slaveBaseNum = 2

const getLevelNum = (level: number): number => {
    return 1
}

//宝宝属性
export interface SlaveAbility {
    //hp
    MaxHp: number
    //攻击
    DCMin: number
    DCMax: number
    //防御
    ACMin: number
    ACMax: number
    //魔域
    MACMin: number
    MACMax: number
}

//配置
export interface SlaveSet {
    //名称
    name: string,
    //召唤等级
    level: number,
    //需要的技能id
    skillLevel: number,
    //所属技能
    skillName: string,
    //基础属性
    slaveBaseAbility: SlaveAbility,
}

export class SlaveManage {
    slaveMap: Map<string, SlaveSet>;
    skillSlaveMap: Map<string, SlaveSet>;
    constructor() {
        this.slaveMap = new Map<string, SlaveSet>();
        this.skillSlaveMap = new Map<string, SlaveSet>();
        for (let i = 0; i < AllSlaveSet.length; i++) {
            let item: SlaveSet = AllSlaveSet[i] as SlaveSet
            this.slaveMap.set(item.name, item);
        }
        this.skillSlaveMap.set(KulouSet.skillName, KulouSet as SlaveSet)
        this.skillSlaveMap.set(DogSet.skillName, DogSet as SlaveSet)
    }

    onMagicSpell(Player: TPlayObject, UserMagic: TUserMagic, nTargetX: number, nTargetY: number,
        Target: TActor, Handled: boolean): boolean {
        if (UserMagic.Name == "诱惑之光") {
            //怪物存在 并且没有死亡 没有主人
            if (checkActor(Target) && !Target.Master) {
                let set: SlaveSet = this.slaveMap.get(Target.Name);
                if (set && set.skillName === UserMagic.Name) {
                    if (set.level > Player.Level) {
                        return true;
                    }
                    if (set.skillLevel > UserMagic.GetStrengthen()) {
                        return true;
                    }
                    let slaveSet: SlaveAbility = getSlaveAbility(set, UserMagic);
                    if (slaveSet) {

                        if (this.checkSlaveNum(Player, set, UserMagic)) {
                            // if (randomInRange(5) === 0) {
                            this.setMaster(Target, Player, UserMagic)
                            // }
                        }


                    }

                    return true;
                }
            }
        }
        else {
            let set = this.skillSlaveMap.get(UserMagic.Name);

            if (set) {
                let slaveSet: SlaveAbility = getSlaveAbility(set, UserMagic);
                if (slaveSet) {

                    if (this.checkSlaveNum(Player, set, UserMagic)) {
                        loopMongen(Player.Map.MapID, set.name, Player.MapX, Player.MapY, 5, 1, (list: TActorList) => {
                            if (list.Count > 0) {
                                let slave = list.Actor(0);

                                this.setMaster(slave, Player, UserMagic)

                            }
                        });
                    }
                }
                return true;
            }
        }
        return false
    }

    //获取下属最大等级
    getSlaveMaxLevel(Player: TPlayObject, Slave: TActor): number {
        let maxLevel = Player.GetNVar(ActorNkeyEnum.SlaveAddMaxLevel) + 200;
        let name = Slave.GetSVar(ActorSkeyEnum.MonName)
        if (this.slaveMap.has(name)) {
            let set: SlaveSet = this.slaveMap.get(name)

            let magic: TUserMagic = Player.FindSkill(set.skillName);
            maxLevel += magic ? magic.GetStrengthen() * 80 : 0
        }
        return maxLevel
    }

    onSlaveKillMonster(Player: TPlayObject, Slave: TActor, Monster: TActor): void {

        let level = Slave.GetNVar(ActorNkeyEnum.SlaveLevel)
        let num = Slave.GetNVar(ActorNkeyEnum.SlaveKillNum)


        let maxLevel = this.getSlaveMaxLevel(Player, Slave);

        if (level < maxLevel) {
            let upNum = getLevelNum(level)
            num++;
            if (num >= upNum) {
                num = 0
                level++;
                Slave.SetNVar(ActorNkeyEnum.SlaveLevel, level)
                Slave.SetNVar(ActorNkeyEnum.SlaveKillNum, num)
                this.updateSlaveAbility(Slave, Player)
            }
            else {
                Slave.SetNVar(ActorNkeyEnum.SlaveKillNum, num)
            }
        }
    }

    //给新宝宝设置主人
    setMaster(slave: TActor, play: TPlayObject, UserMagic?: TUserMagic, level?: number) {
        slave.SetSVar(ActorSkeyEnum.MonName, slave.Name);
        let slaveLevel
        if (!UserMagic) {
            slaveLevel = level
        }
        else {
            slaveLevel = (play.GetNVar(ActorNkeyEnum.SlaveAddLevel) || 0) + UserMagic.GetStrengthen() * 40;
        }
        slave.SetNVar(ActorNkeyEnum.SlaveLevel, slaveLevel);
        slave.SetNVar(ActorNkeyEnum.SlaveKillNum, 0);

        slave.SetMaster(play);
        slave.SetMasterRoyaltyTick(MaxIntNum)

        slave.TriggerDamageEvent = true;
        slave.SetTargetActor(null);
        // slave.TriggerDieEvent = true;
        // slave.TriggerKillerEvent = true;

        this.updateSlaveAbility(slave, play)

        slave.HP = slave.MaxHP;
    }

    //根据配置和技能等级获取宝宝属性配置
    updateSlaveAbility(slave: TActor, play?: TPlayObject): void {
        if (!checkActor(slave)) {
            return
        }
        if (!play) {
            let master = slave.Master;
            //主人不是人物 
            if (!checkActor(master) || !master.IsPlayer()) {
                return
            }
            play = master as TPlayObject;
        }

        //宝宝的真实名称
        let name = slave.GetSVar(ActorSkeyEnum.MonName)

        let set: SlaveSet = this.slaveMap.get(name)
        let magic: TUserMagic = play.FindSkill(set.skillName);
        let slaveSet = getSlaveAbility(set, magic)
        if (!slaveSet) {
            return;
        }



        let level = slave.GetNVar(ActorNkeyEnum.SlaveLevel);
        let bl = (play.GetNVar(ActorNkeyEnum.SlaveAddAbilityPer) || 0) / MaxPercentNum + 1

        if (name == "白虎") {
            slave.SetNVar(ActorNkeyEnum.DamageAdd, (play.GetNVar(ActorNkeyEnum.SlaveDamageAdd) || 0) + 250)
            slave.SetNVar(ActorNkeyEnum.DamageAddPer, (play.GetNVar(ActorNkeyEnum.SlaveDamageAddPer) || 0) + 500)
            slave.SetNVar(ActorNkeyEnum.DamageCut, (play.GetNVar(ActorNkeyEnum.SlaveDamageCut) || 0) + 250)
            slave.SetNVar(ActorNkeyEnum.DamageCutPer, (play.GetNVar(ActorNkeyEnum.SlaveDamageCutPer) || 0) + 1000)
        }
        else {
            slave.SetNVar(ActorNkeyEnum.DamageAdd, play.GetNVar(ActorNkeyEnum.SlaveDamageAdd) || 0)
            slave.SetNVar(ActorNkeyEnum.DamageAddPer, play.GetNVar(ActorNkeyEnum.SlaveDamageAddPer) || 0)
            slave.SetNVar(ActorNkeyEnum.DamageCut, play.GetNVar(ActorNkeyEnum.SlaveDamageCut) || 0)
            slave.SetNVar(ActorNkeyEnum.DamageCutPer, play.GetNVar(ActorNkeyEnum.SlaveDamageCutPer) || 0)
        }

        let dis = (play.GetNVar(ActorNkeyEnum.SlaveDis) || 0) + 1;
        slave.SetAttackRange(dis)
        //血量
        let MaxHp = slaveSet.MaxHp + level * HpAddLevel + play.MaxHP * HpAddPer * bl
        let ACMax = slaveSet.ACMax + level * AcAddLevel + play.ACMax * AcAddPer * bl
        let ACMin = slaveSet.ACMin + level * AcAddLevel + play.ACMin * AcAddPer * bl
        let MACMax = slaveSet.MACMax + level * AcAddLevel + play.MACMax * AcAddPer * bl
        let MACMin = slaveSet.MACMin + level * AcAddLevel + play.MACMin * AcAddPer * bl
        let DCMin = slaveSet.DCMin + level * DcAddLevel
        let DCMax = slaveSet.DCMax + level * DcAddLevel
        switch (play.Job) {
            case 0:
                DCMin += play.DCMin * DcAddPer * bl
                DCMax += play.DCMax * DcAddPer * bl
                break
            case 1:
                DCMin += play.MCMin * DcAddPer * bl
                DCMax += play.MCMax * DcAddPer * bl
                break
            case 2:
                DCMin += play.SCMin * DcAddPer * bl
                DCMax += play.SCMax * DcAddPer * bl
                break
        }

        slave.MaxHP = Math.floor(MaxHp);
        slave.ACMax = Math.floor(ACMax);
        slave.ACMin = Math.floor(ACMin);
        slave.MACMax = Math.floor(MACMax);
        slave.MACMin = Math.floor(MACMin);
        slave.DCMin = Math.floor(DCMin);
        slave.DCMax = Math.floor(DCMax);

        if (DCMax < DCMin) {
            let str = `玩家${play.Name}的${level}的宝宝${slave.Name}的基础属性为${JSON.stringify(slaveSet)}\n
                最终属性:${slave.MaxHP} ${slave.ACMax} ${slave.ACMin} ${slave.MACMax}  ${slave.MACMin}  ${slave.DCMin}  ${slave.DCMax}`
            saveLog(str, LogType.Slave, play)
        }

        // slave.Name = `${name}\\(等级:${level})\\`

    }

    //检查宠物数量
    checkSlaveNum(play: TPlayObject, set: SlaveSet, magic: TUserMagic) {
        let num = getSkillSlaveNum(magic)

        let total = (play.GetNVar(ActorNkeyEnum.SlaveNum) || 0) + slaveBaseNum
        //检查数量
        if (total > play.SlaveCount) {
            if (num) {
                let slaveNum = this.getSkillSlaveCount(play, set.skillName)
                if (slaveNum >= num) {
                    return false;
                }
            }
        }
        else {
            return false;
        }
        return true;
    }

    //获取属于指定技能的宝宝数量
    getSkillSlaveCount(play: TPlayObject, skillName: string): number {
        let num = 0;
        for (let i = 0; i < play.SlaveCount; i++) {
            let actor: TActor = play.GetSlave(i);
            let actname = actor.GetSVar(ActorSkeyEnum.MonName);
            if (this.slaveMap.has(actname)) {
                let set: SlaveSet = this.slaveMap.get(actname)
                if (set.skillName === skillName) {
                    num++
                }
            }

        }
        return num;
    }

    //装备切换的时候检查所有宠物
    checkAllSlave(play: TPlayObject) {
        let skillSlaveMax = {};//技能最大宝宝数 没有就是0 无限制就是最大值
        let skillSlaveNum = {};

        for (let i = 0; i < SlaveSkillList.length; i++) {
            let magic: TUserMagic = play.FindSkill(SlaveSkillList[i])
            if (magic) {
                skillSlaveMax[SlaveSkillList[i]] = getSkillSlaveNum(magic)
            }
            else {
                skillSlaveMax[SlaveSkillList[i]] = 0
            }
            skillSlaveNum[SlaveSkillList[i]] = 0;
        }


        //宝宝总数
        let maxSlaveNum = (play.GetNVar(ActorNkeyEnum.SlaveNum) || 0) + slaveBaseNum


        let delActorList: Array<TActor> = [];

        //检查宝宝数量
        for (let i = 0; i < play.SlaveCount; i++) {
            let slave: TActor = play.GetSlave(i);
            if (!checkActor(slave)) {
                continue
            }

            let actname = slave.GetSVar(ActorSkeyEnum.MonName);

            let check = true;
            if (this.slaveMap.has(actname)) {
                let set: SlaveSet = this.slaveMap.get(actname);
                let skillName = set.skillName;
                let maxNum = skillSlaveMax[skillName];
                let num = skillSlaveNum[skillName];
                if (num >= maxNum) {
                    check = false;
                }
                else {
                    skillSlaveNum[skillName]++;
                }
            }
            else {
                check = false;
            }

            if (!check || i >= maxSlaveNum) {
                delActorList.push(slave)
            }
            else {
                let maxSlaveLevel = this.getSlaveMaxLevel(play, slave)
                let level = slave.GetNVar(ActorNkeyEnum.SlaveLevel)
                if (level > maxSlaveLevel) {
                    slave.SetNVar(ActorNkeyEnum.SlaveLevel, maxSlaveLevel)
                    slave.SetNVar(ActorNkeyEnum.SlaveKillNum, 0)
                }

                this.updateSlaveAbility(slave, play)
            }
        }

        for (let i = delActorList.length - 1; i >= 0; i--) {
            let slave = delActorList[i]
            slave.MakeGhost();
        }

    }

    //保存宝宝
    saveSlave(play: TPlayObject, notKillSlave?: boolean) {
        if (play.Death) {
            return
        }
        // let g99 = GameLib.GetGVar(99)
        //土城安全区可以保存宝宝
        // if (play.Map.MapID == "3" && play.GetInSafeZone())) {
        play.MapMove('3', 333, 333)
        let list = []
        for (let i = play.SlaveCount - 1; i >= 0; i--) {
            let slave: TActor = play.GetSlave(i);
            if (checkActor(slave)) {
                let name = slave.GetSVar(ActorSkeyEnum.MonName)
                let level = slave.GetNVar(ActorNkeyEnum.SlaveLevel);
                let obj = {
                    name,
                    level,
                }
                list.push(obj)
                if (!notKillSlave) {
                    slave.MakeGhost();
                }

            }
        }
        if (list.length > 0) {
            play.V.slaveList = list
        }

        // }
    }

    loadSlave(play: TPlayObject) {
        let list = play.V.slaveList;
        play.V.slaveList = [];
        if (list && list.length > 0) {
            for (let i = 0; i < list.length; i++) {
                let item = list[i];
                loopMongen(play.Map.MapID, item.name, play.MapX, play.MapY, 5, 1, (list: TActorList) => {
                    if (list.Count > 0) {
                        let slave = list.Actor(0);
                        this.setMaster(slave, play, null, item.level)
                    }
                });
            }
        }
    }
}

//根据配置和技能等级获取宝宝属性配置
export function getSlaveAbility(set: SlaveSet, magic: TUserMagic): SlaveAbility {
    if (!set || !magic) {
        return null;
    }
    if (!set.slaveBaseAbility) {
        return null;
    }

    let abi: SlaveAbility = getSlaveAddAbiBySkill(magic);
    let newAbi = {} as SlaveAbility;
    newAbi.MaxHp = abi.MaxHp + set.slaveBaseAbility.MaxHp;
    newAbi.DCMin = abi.DCMin + set.slaveBaseAbility.DCMin;
    newAbi.DCMax = abi.DCMax + set.slaveBaseAbility.DCMax;
    newAbi.ACMin = abi.ACMin + set.slaveBaseAbility.ACMin;
    newAbi.ACMax = abi.ACMax + set.slaveBaseAbility.ACMax;
    newAbi.MACMin = abi.MACMin + set.slaveBaseAbility.MACMin;
    newAbi.MACMax = abi.MACMax + set.slaveBaseAbility.MACMax;
    return newAbi

}

/**
 * 获取指定技能的宠物数目
 * @param skillName 
 * @param magic 
 * @returns 
 */
export function getSkillSlaveNum(magic: TUserMagic) {
    let list = SkillSlaveNumSet[magic.Name]
    let num = MaxIntNum;
    if (list && list.length > 0) {
        let lv = magic.GetStrengthen();
        num = getArrayItem(list, lv)
    }
    return num;
}
